/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.service.excel.impl;


import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.poi.excel.WorkbookUtil;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.Maps;
import com.je.common.base.DynaBean;
import com.je.common.base.document.InternalFileBO;
import com.je.common.base.exception.PlatformException;
import com.je.common.base.exception.PlatformExceptionEnum;
import com.je.common.base.service.rpc.DocumentInternalRpcService;
import com.je.common.base.util.ArrayUtils;
import com.je.common.base.util.StringUtil;
import com.je.common.base.util.SystemProperty;
import com.je.document.model.FileBO;
import com.je.ibatis.extension.conditions.ConditionsWrapper;
import com.je.meta.rpc.excel.AbstractExcelRpcExportService;
import com.je.meta.service.ExcelService;
import org.apache.poi.ss.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 模板样式导出
 */
@Service("excelRpcTemplateExportService")
public class ExcelRpcTemplateExportServiceImpl extends AbstractExcelRpcExportService   {

    @Autowired
    private ExcelService excelService;

    @Autowired
    private DocumentInternalRpcService documentInternalRpcService;

    @Override
    public InputStream export(JSONObject params, HttpServletRequest request) {
        String queryType = params.getString("queryType");
        String styleType = params.getString("styleType");
        String funcId = params.getString("funcId");
        String sheetId = params.getString("sheetId");
        String title = params.getString("title");
        String fileKey = StringUtil.getStringParameter(request,"fileKey");

        //查询数据
        List<DynaBean> datas = expData(params, request);
        if (datas.size() > 1048570) {
            throw new PlatformException("数据条数大于1048570,无法导出!", PlatformExceptionEnum.JE_CORE_EXCEL_EXP_ERROR);
        }
        if (StringUtil.isEmpty(sheetId)) {
            throw new PlatformException("未选择模板,无法导出!", PlatformExceptionEnum.JE_CORE_EXCEL_EXP_ERROR);
        }
        List<Map<String, Object>> list = excelService.funcTemplateListById(sheetId);
        //查询列配置
        List<DynaBean> fields = metaService.select("JE_CORE_EXCELFIELD", ConditionsWrapper.builder().apply(String.format(" AND JE_CORE_EXCELSHEET_ID = '%s' AND EXCELFIELD_COLUMN is not null AND EXCELFIELD_COLUMN != ''", sheetId)));
        //获取模板文件流
        File file = documentInternalRpcService.readFile(fileKey);
        InternalFileBO internalFileBO = documentInternalRpcService.selectFileByKey(fileKey);

        //缓存为临时文件
        String PACKAGE_TEMP_FILE_PATH = SystemProperty.getRootPath() + "/excel_temp/%s.%s";
        String tempFilePath = String.format(PACKAGE_TEMP_FILE_PATH, System.currentTimeMillis(), internalFileBO.getSuffix());
        //String tempFilePath ="C:\\Users\\77279\\Desktop\\test\\测试导出_2022-04-15.xls";
        try {
            FileUtil.writeFromStream(new FileInputStream(file), tempFilePath);
            IoUtil.close(new FileInputStream(file));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        File tempFile = new File(tempFilePath);
        //开始位置
        int sheetIndex = Integer.parseInt(list.get(0).get("SY_ORDERINDEX").toString()) - 1;
        int startRow = Integer.parseInt(list.get(0).get("STARTROWS").toString()) - 1;

        //创建excel操作对象
        Workbook book = WorkbookUtil.createBook(tempFile);
        Sheet sheet = book.getSheetAt(sheetIndex);

        //获取默认样式
        int defaultColumnWidth = sheet.getDefaultColumnWidth();
        float defaultRowHeightInPoints = sheet.getDefaultRowHeightInPoints();
        Row firstRow = sheet.getRow(startRow);
        CellStyle defRowStyle = book.createCellStyle();

        CellStyle firstColumnStyle = null;
        Map<Integer, CellStyle> defaultcolumnStyles = Maps.newHashMap();
        if (firstRow != null) {
            defRowStyle = firstRow.getRowStyle();
            defaultRowHeightInPoints = firstRow.getHeightInPoints();
            //获取列默认样式
            int columnNum = firstRow.getPhysicalNumberOfCells();
            for (int i = 0; i < columnNum; i++) {
                Cell cell = firstRow.getCell(i);
                if (cell != null) {
                    //清空示例数据
                    cell.setCellValue("");
                    //获取样式
                    CellStyle cellStyle = cell.getCellStyle();
                    if (cellStyle != null) {
                        defaultcolumnStyles.put(i, cellStyle);
                        if (firstColumnStyle == null) {
                            firstColumnStyle = book.createCellStyle();
                            firstColumnStyle.cloneStyleFrom(cellStyle);
                            //单元格默认设置文本
                            firstColumnStyle.setDataFormat(book.createDataFormat().getFormat("@"));
                        }
                    }
                }
            }
        }
        //field转换map,key为列对应的数字， A -> 0; Z -> 25; AA -> 26;
        Map<Integer, DynaBean> fieldMap = fields.stream().filter(p -> StringUtil.isNotEmpty(p.getStr("EXCELFIELD_COLUMN")))
                .collect(Collectors.toMap(p -> excelColStrToNum(p.getStr("EXCELFIELD_COLUMN")), column -> {
                    //设置 RESOURCEFIELD_XTYPE,RESOURCEFIELD_CONFIGINFO  方便调用公共方法
                    column.setStr("RESOURCEFIELD_XTYPE", column.getStr("EXCELFIELD_XTYPE"));
                    column.setStr("RESOURCEFIELD_CONFIGINFO", column.getStr("EXCELFIELD_CONFIGINFO"));
                    return column;
                }));

        //获取字典信息
        Map<String, Map<String, String>> ddInfos = excelRpcService.buildDicDatas(fields);

        //填充数据
        for (int i = 0; i < datas.size(); i++) {

            //行号
            int rowNum = startRow + i;

            //获取行
            Row row = sheet.getRow(rowNum);
            if (row == null) {
                row = sheet.createRow(rowNum);
                row.setHeightInPoints(defaultRowHeightInPoints);
                if (defRowStyle != null) {
                    row.setRowStyle(defRowStyle);
                }
            }
            //数据
            DynaBean data = datas.get(i);
            //填充列
            for (Map.Entry<Integer, DynaBean> entry : fieldMap.entrySet()) {

                int colIndex = entry.getKey();
                DynaBean column = entry.getValue();

                Cell cell = row.getCell(colIndex);
                if (cell == null) {
                    cell = row.createCell(colIndex);
                    CellStyle cellStyle = defaultcolumnStyles.get(colIndex);
                    if (cellStyle != null) {
                        cell.setCellStyle(cellStyle);
                    } else if (firstColumnStyle != null) {
                        cell.setCellStyle(firstColumnStyle);
                    }
                }
                String columnCode = column.getStr("EXCELFIELD_CODE");
                String value = data.getStr(columnCode, "");
                String xtype = column.getStr("EXCELFIELD_XTYPE");
                if (ArrayUtils.contains(new String[]{"rgroup", "cgroup", "cbbfield"}, xtype)) {
                    //获取字典对应值
                    String ddValue = getDdValue(ddInfos, column, value);
                    cell.setCellValue(ddValue);
                } else if ("rownumberer".equalsIgnoreCase(xtype)) {
                    cell.setCellValue(i + 1);
                } else {
                    cell.setCellValue(value);
                }
            }
        }
        try {
            // 写出数据到流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            book.write(out);
            out.flush();
            ByteArrayInputStream inputStream = new ByteArrayInputStream(out.toByteArray());
            IoUtil.close(out);
            IoUtil.close(book);
            return inputStream;
        } catch (Exception e) {
            e.printStackTrace();
        }
//        return expUseTemplate(sheetId, datas);
        return FileUtil.getInputStream(tempFile);
    }


    /**
     * 获取字典字段的code的name值
     *
     * @param ddInfos
     * @param column
     * @param codeValue
     * @return
     */
    private String getDdValue(Map<String, Map<String, String>> ddInfos, DynaBean column, String codeValue) {
        String xtype = column.getStr("RESOURCEFIELD_XTYPE");
        //多选框
        Map<String, String> ddItems = null;
        String configInfo = column.getStr("RESOURCEFIELD_CONFIGINFO");
        if (StringUtil.isNotEmpty(configInfo)) {
            String ddCode = configInfo.split(",")[0];
            ddItems = ddInfos.get(ddCode);
        }
        if (ddItems != null) {
            if ("cgroup".equals(xtype)) {
                if (StringUtil.isNotEmpty(codeValue)) {
                    String[] codeValues = codeValue.split(",");
                    for (Integer i = 0; i < codeValues.length; i++) {
                        if (StringUtil.isNotEmpty(codeValues[i]) && ddItems.get(codeValues[i]) != null) {
                            codeValues[i] = ddItems.get(codeValues[i]);
                        }
                    }
                    return StringUtil.buildSplitString(codeValues, ",");
                } else {
                    return codeValue;
                }
            } else {
                if (StringUtil.isNotEmpty(codeValue) && ddItems.get(codeValue) != null) {
                    return ddItems.get(codeValue);
                } else {
                    return codeValue;
                }
            }
        } else {
            return codeValue;
        }
    }

    /**
     * excel列转数字
     * A -> 0; Z -> 25; AA -> 26;
     *
     * @param colStr excel列
     * @return int
     */
    public static int excelColStrToNum(String colStr) {
        int num = 0;
        int result = -1;
        for (int i = 0; i < colStr.length(); i++) {
            char ch = colStr.charAt(colStr.length() - i - 1);
            num = (int) (ch - 'A' + 1);
            num *= Math.pow(26, i);
            result += num;
        }
        return result;
    }

}
